﻿namespace BM.Tools.WebControls.MForm.Controls.Helper
{    
    using System.Web.UI;
    using System.Web.UI.WebControls;

    using DefaultTemplates;

    using Items;

    using ValueHandlers;

    /// <summary>
    /// This is a <see cref="PlaceHolder"/> that is responsible for keeping the <see cref="ValueHandler" /> control inside.
    /// </summary>
    internal class ValueHandlerHolder : PlaceHolder
    {
        private ValueHandler valueHandler;

        /// <summary>
        /// Initializes a new instance of the <see cref="ValueHandlerHolder"/> class.
        /// </summary>
        /// <param name="item">
        /// The leaf item.
        /// </param>
        public ValueHandlerHolder(LeafItem item)
        {
            Item = item;            
        }

        /// <summary>
        /// Gets Controls.
        /// </summary>
        public override ControlCollection Controls
        {
            get
            {
                EnsureChildControls();
                return base.Controls;
            }
        }

        /// <summary>
        /// Gets the leaf item.
        /// </summary>
        public LeafItem Item
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets ValueHandler.
        /// </summary>
        public ValueHandler ValueHandler
        {
            get
            {
                EnsureValueHandlerCreated();
                return valueHandler;
            }

            set
            {
                if (value == valueHandler)
                {
                    return;
                }

                SetValueHandlerPreservingValue(value);
            }
        }

        /// <summary>
        /// Gets the item basis value handler template or a <see cref="TextBoxValueHandlerTemplate"/> if none is set.
        /// </summary>
        protected ITemplate Template
        {
            get
            {
                if (Item.Basis.ValueHandler == null)
                {
                    return new TextBoxValueHandlerTemplate();
                }

                return Item.Basis.ValueHandler;
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> 
        /// object that contains the event data. 
        /// </param>
        protected override void OnInit(System.EventArgs e)
        {
            base.OnInit(e);
            EnsureValueHandlerCreated();
        }

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            EnsureValueHandlerCreated();
        }

        private void EnsureValueHandlerAdded()
        {
            if (valueHandler.Parent == this)
            {
                return;
            }

            Controls.Clear();
            Controls.Add(valueHandler);
        }

        private void EnsureValueHandlerCreated()
        {
            if (valueHandler == null)
            {
                valueHandler = GetValueHandlerFromTemplate();
            }

            EnsureValueHandlerAdded();
        }

        private ValueHandler GetValueHandlerFromTemplate()
        {
            var valueHandlerPanel = new PlaceHolder();
            Template.InstantiateIn(valueHandlerPanel);
            foreach (Control c in valueHandlerPanel.Controls)
            {
                var handler = c as ValueHandler;
                if (handler != null)
                {
                    return handler;
                }
            }

            return null;
        }

        private void SetValueHandlerPreservingValue(ValueHandler newValueHandler)
        {
            var value = (valueHandler != null) ? valueHandler.Value : null;
            valueHandler = newValueHandler;
            if (value != null)
            {
                valueHandler.Value = value;
            }

            EnsureValueHandlerAdded();
        }
    }
}
